package org.gdstash.db;

import org.gdstash.util.GDMsgFormatter;
import org.gdstash.util.GDMsgLogger;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class DBViewItemSkill implements Comparable<DBViewItemSkill> {
    private static final int ROW_SKILL_ID = 1;
    private static final int ROW_NAME = 2;
    private String skillID;
    private String name;

    public DBViewItemSkill() {
        this.skillID = null;
        this.name = null;
    }

    public DBViewItemSkill(final String name) {
        this();
        this.name = name;
    }

    private static List<DBViewItemSkill> wrap(final ResultSet rs) throws SQLException {
        final LinkedList<DBViewItemSkill> list = new LinkedList<DBViewItemSkill>();
        while (rs.next()) {
            final DBViewItemSkill skill = new DBViewItemSkill();
            skill.skillID = rs.getString(1);
            skill.name = rs.getString(2);
            if (skill.name != null) {
                final ByteBuffer buffer = StandardCharsets.UTF_8.encode(skill.name);
                final String utf8 = StandardCharsets.UTF_8.decode(buffer).toString();
                skill.name = utf8;
            }
            list.add(skill);
        }
        return list;
    }

    @Override
    public boolean equals(final Object o) {
        if (o == null) {
            return false;
        }
        if (!o.getClass().equals(DBViewItemSkill.class)) {
            return false;
        }
        final DBViewItemSkill skill = (DBViewItemSkill) o;
        if (this.skillID == null) {
            return skill.skillID == null;
        }
        return this.skillID.equals(skill.skillID);
    }

    @Override
    public int hashCode() {
        return this.skillID.hashCode();
    }

    @Override
    public int compareTo(final DBViewItemSkill skill) {
        if (skill == null) {
            return -1;
        }
        return this.name.compareTo(skill.name);
    }

    public String getSkillID() {
        return this.skillID;
    }

    public static List<DBViewItemSkill> getItemSkills() {
        final List<DBViewItemSkill> list = new LinkedList<DBViewItemSkill>();
        final List<DBViewItemSkill> itemList = getSkillsFromItem();
        final List<DBViewItemSkill> affixList = getSkillsFromAffix();
        if (itemList != null) {
            for (final DBViewItemSkill skill : itemList) {
                if (skill == null) {
                    continue;
                }
                if (skill.name == null) {
                    continue;
                }
                boolean found = false;
                for (final DBViewItemSkill itemSkill : list) {
                    if (itemSkill.skillID.equals(skill.skillID)) {
                        found = true;
                        break;
                    }
                }
                if (found) {
                    continue;
                }
                list.add(skill);
            }
        }
        if (affixList != null) {
            for (final DBViewItemSkill skill : affixList) {
                if (skill == null) {
                    continue;
                }
                if (skill.name == null) {
                    continue;
                }
                boolean found = false;
                for (final DBViewItemSkill itemSkill : list) {
                    if (itemSkill.skillID.equals(skill.skillID)) {
                        found = true;
                        break;
                    }
                }
                if (found) {
                    continue;
                }
                list.add(skill);
            }
        }
        Collections.<DBViewItemSkill>sort(list);
        return list;
    }

    private static List<DBViewItemSkill> getSkillsFromItem() {
        List<DBViewItemSkill> list = null;
        final String command = "SELECT DISTINCT GD_SKILL.SKILL_ID, GD_SKILL.NAME FROM GD_ITEM, GD_SKILL WHERE GD_ITEM.ITEM_SKILL_ID IS NOT NULL AND GD_ITEM.ITEM_SKILL_ID = GD_SKILL.SKILL_ID ORDER BY GD_SKILL.NAME";
        try (final Connection conn = GDDBData.getConnection();
             final PreparedStatement ps = conn.prepareStatement(command)) {
            try (final ResultSet rs = ps.executeQuery()) {
                list = wrap(rs);
                conn.commit();
            } catch (SQLException ex) {
                throw ex;
            }
        } catch (SQLException ex2) {
            final Object[] args = {"-", "DBViewItemSkill"};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_READ_TABLE_BY_ID", args);
            GDMsgLogger.addError(msg);
            GDMsgLogger.addError(ex2);
        }
        return list;
    }

    private static List<DBViewItemSkill> getSkillsFromAffix() {
        List<DBViewItemSkill> list = null;
        final String command = "SELECT DISTINCT GD_SKILL.SKILL_ID, GD_SKILL.NAME FROM GD_AFFIX, GD_SKILL WHERE GD_AFFIX.ITEM_SKILL_ID IS NOT NULL AND GD_AFFIX.ITEM_SKILL_ID = GD_SKILL.SKILL_ID ORDER BY GD_SKILL.NAME";
        try (final Connection conn = GDDBData.getConnection();
             final PreparedStatement ps = conn.prepareStatement(command)) {
            try (final ResultSet rs = ps.executeQuery()) {
                list = wrap(rs);
                conn.commit();
            } catch (SQLException ex) {
                throw ex;
            }
        } catch (SQLException ex2) {
            final Object[] args = {"-", "DBViewItemSkill"};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_READ_TABLE_BY_ID", args);
            GDMsgLogger.addError(msg);
            GDMsgLogger.addError(ex2);
        }
        return list;
    }

    public String getName() {
        return this.name;
    }

    @Override
    public String toString() {
        return this.name;
    }
}
